package thread;

import java.util.PriorityQueue;

/**
 * @Author liangzai
 * @Description:
 */

class MyTimerTask implements Comparable<MyTimerTask>{
    private long time;

    private Runnable runnable;

    public MyTimerTask(long time, Runnable runnable) {
        this.time = time;
        this.runnable = runnable;
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time - o.time);
    }

    public long getTime() {
        return time;
    }

    public Runnable getRunnable() {
        return runnable;
    }
}

class MyTimer{
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
    private Object locker = new Object();

    public MyTimer(){
        synchronized (locker) {
            Thread t = new Thread(() -> {
                try {
                    while (true) {
                        synchronized (locker) {
                            while (queue.isEmpty()) {
                                locker.wait();
                            }
                            long time = queue.peek().getTime();
                            if (System.currentTimeMillis() < time) {
                                locker.wait((int)(time - System.currentTimeMillis()));
                                //continue;
                            } else {
                                //System.out.println(System.currentTimeMillis());
                                queue.poll().getRunnable().run();
                                //System.out.println(System.currentTimeMillis());
                            }
                        }
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            });
            t.start();
        }
    }

    public void schedule(Runnable runnable,long delaytime){
        synchronized (locker) {
            MyTimerTask myTimerTask = new MyTimerTask(delaytime + System.currentTimeMillis(), runnable);
            queue.offer(myTimerTask);
            locker.notify();
        }
    }
}

public class Demo2 {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(()->{
            System.out.println(System.currentTimeMillis());
            System.out.println("hello 3000");
        },3000);
        timer.schedule(()->{
            System.out.println(System.currentTimeMillis());
            System.out.println("hello 2000");
        },2000);
        timer.schedule(()->{
            System.out.println(System.currentTimeMillis());
            System.out.println("hello 1000");
        },1000);
    }
}
